home *** CD-ROM | disk | FTP | other *** search
- /*
- * Megamax C inline ASM version of Twister.
- * Converted from AS68 format dlm 12/14/86.
- * AS68 version by David Small before that date.
- * Used for the MegAMin HD backup program.
- */
-
- /* routine that are callable from C are: */
- extern twister();
-
- /* global variables */
- int thedisk, dblsided, sectoroffset; /* input parameters */
- long buffer;
-
- int badflag; /* bad sector error flag */
-
- /* local variables */
- static int theside, thetrack, twistsectorno, sectorno, retrycnt,
- cdev, ctrack, csect, cside, ccount, A7t, interlv,
- virgin, def_error, curr_err;
- static long cdma, edma, tmpdma, saveA2;
-
- /* now the defines (AS68 equ's) */
-
- /* tunable values */
- #define retries 2 /* default # of retries -1 */
- #define midretry 1 /* "middle" retry, when to reseek */
- #define timeout 0x40000 /* short timeout, motor already on */
- #define ltimeout 0x60000 /* long timeout, to startup motor */
-
- /* Floppy state variables in DSB: RAM usage */
- #define recal 0xff00 /* recalibrate flag */
- #define dcurtrack 0 /* current track number */
- #define dseekrt dcurtrack+2 /* seek rate */
- #define dsbsiz dseekrt+2 /* size of a DSB */
-
- /* hardware equates */
- /* DMA chip */
- #define diskctl 0xffff8604 /* disk controller data access */
- #define fifo 0xffff8606 /* DMA mode control / status */
- #define dmahigh 0xffff8609 /* DMA base high */
- #define dmamid 0xffff860b /* DMA base mid */
- #define dmalow 0xffff860d /* DMA base low */
-
- /* 1170 select values */
- #define cmdreg 0x80 /* select command register */
- #define trkreg 0x82 /* select track register */
- #define secreg 0x84 /* select sector register */
- #define datareg 0x86 /* select data register */
-
- /* GI sound chip (drive a/b select lines and side select) */
- #define giselect 0xffff8800 /* (W) sound chip register select */
- #define giread 0xffff8800 /* (R) sound chip read data */
- #define giwrite 0xffff8802 /* (W) sound chip write data */
- #define giporta 0x0e /* GI register # for i/o port A */
-
- /* 68901 mfp chip */
- #define mfp 0xfffffa00 /* mfp base */
- #define gpip mfp+1 /* general purpose i/o */
-
- /* ROM burn dates */
- #define old_rom 0x11201985L
- #define new_rom 0x04221987L
-
- #define rom_date 0x00fc0018L /* rom burn date address */
-
- /* misc defines */
- #define seekrate 3
- #define dsb0old 0xa06
- #define dsb0new 0xa4c /* for the Mega ROMs */
- #define dsb1old 0xa0a
- #define dsb1new 0xa50
- #define flock 0x43e
-
- asm { /* start of inline ASM */
-
- /*
- * All the following is munged code from AS68 (that's why the
- * weird format). The AS68 code was munged from the BIOS
- * source. And most of this is from the FDC article in Start
- * issue number 3.
- *
- * Anyway, we apologize for the mess, but heh it works.
- *
- * Oh yes. The labels are usually on nops, not empty lines. Thats
- * because AS68 occasionally pukes on labels on empty lines. And
- * I didn't take the time to remove them. (Megamax doesn't care.)
- *
- */
-
- ;****************************************************************
- ; Twister: Faster formatter (zipformat) hack. MM version *
- ; Copyright (c) 1986, 1987 START Magazine (as usual) *
- ; Written by David Y. Small & Dan Moore *
- ;****************************************************************
- ; *
- ; Dedication: *
- ; *
- ; For Bill The Cat: because he's twisted, too. *
- ; *
- ;****************************************************************
- ;
- ; code begins.
- ;
- ; PASS ME THIS STUFF DAN! Then SHAVE! For God's sakes! What
- ; are you trying to do, look like Fidel Castro?
- ;
- ; And get SOME BEER in here okay? Sheesh!
- ;
- ; input integers (if coming from C):
- ;
- ; dblsided: 0000 or ffff
- ; thedisk: 0 = a, 1 = b
- ;*************************************************************
-
-
- ;********************************************************
- ; Frammatter *
- ;********************************************************
- twister: move.l A2, saveA2(A4) ; everything else saved by the Supexec
-
- clr.w badflag(A4) ; assume no errors
- ;
- ;*** Init vars for formatting loop
- ;
- move.w #0,thetrack(A4) ; start at track 0
-
- move.w #1,twistsectorno(A4) ; twister value
-
- trackloop: nop ; comes here for subseq tracks
-
-
- ;***** FRONT SIDE ***********
- ;**** Setup stack: .. based on read sec command, tweaked for frammat
-
- move.w #0xe5e5,-(A7) ; virgin data -- e5's work okay
- move.l #0x87654321,-(A7) ; magic # to make format work / fmt only
- move.w #1,-(A7) ; sector interleave factor / fmt only
- move.w #0,-(A7) ; ** side.w (relevant) / side: FRONT
- move.w thetrack(A4),-(A7) ; ** track.w (relevant) / same
- move.w #10,-(A7) ; sector.w (irrelevant) / sectors per track
- move.w thedisk(A4),-(A7) ; ** device.w (relevant) / same
- move.l #0,-(A7) ; dummy.l (irreleveant) / same
- move.l buffer(A4),-(A7) ; ** buffer address.l (relevant) / same
- jsr _flopfmt
- adda.l #24,A7 ; Fix stack.
- ;****
- ; Jazz twistsectorno(A4). Look at what it ended up as; set it to
- ; the next track twist depending on that.
- ;
- ; It will end up as "+1" from the last sector formatted, because
- ; the formatter bumps it up.
- ;
- cmpi.w #1,twistsectorno(A4) ; 0-1 transition
- beq fgoto1
- cmpi.w #9,twistsectorno(A4) ; 1-2 transition
- beq fgoto2
- cmpi.w #7,twistsectorno(A4) ; 2-3 transition
- beq fgoto3
- cmpi.w #5,twistsectorno(A4) ; 3-4 transition
- beq fgoto4
- cmpi.w #3,twistsectorno(A4) ; 4-0 transition
- beq fgoto0
-
- dc.b 0x4a
- dc.b 0xfc ; oops, die (illegal instruction)
- ;*****
- ; Really class coding, eh? Oh,well, it's easy and it works, which
- ; twelve other fancy ways of doing this *don't*.
- ;
- fgoto1: move.w #0x9,twistsectorno(A4) ; 9,a,1,2,3,4,5,6,7,8
- bra fkeepformatting
- fgoto2: move.w #0x7,twistsectorno(A4) ; 7,8,9,a,1,2,3,4,5,6
- bra fkeepformatting
- fgoto3: move.w #0x5,twistsectorno(A4) ; 5,6,7,8,9,a,1,2,3,4
- bra fkeepformatting
- fgoto4: move.w #0x3,twistsectorno(A4) ; 3,4,5,6,7,8,9,a,1,2
- bra fkeepformatting
- fgoto0: move.w #0x1,twistsectorno(A4) ; 1,2,3,4,5,6,7,8,9,a
- bra fkeepformatting
- nop
- ;*****
- fkeepformatting: nop
- ;*****
- ; now, do a verify on those sectors.
- ;**** Setup stack: .. based on read sec command, tweaked for frammat
-
- tst.w sectoroffset(A4) ; no verify if 11 to 20 sector numbering
- bne nover1
-
- move.w #0xa,-(A7) ; count.w 2
- move.w #0,-(A7) ; ** side.w (relevant) / side: FRONT 4
- move.w thetrack(A4),-(A7) ; ** track.w (relevant) / same 6
- move.w #0x1,-(A7) ; sector.w (relevant) / starting sector 8
- move.w thedisk(A4),-(A7) ; ** device.w (relevant) / same 0xa
- move.l #0,-(A7) ; dummy.l (irreleveant) / same 0xe
- move.l buffer(A4),-(A7) ; ** buffer address.l (relevant) / same 0x12
-
- move.w #19,-(A7) ; do BIOS _flopver 0x14
- trap #14
- adda.l #20, A7 ; fix stack.
-
- tst.l D0
- bne badsecs
-
- ;****
-
- ;***** BACK SIDE ****** (How kinky Dave. What _are_ you talking about?)
-
- nover1: tst.w dblsided(A4)
- beq nobackside
-
- ;**** Setup stack: .. based on read sec command, tweaked for frammat
-
- move.w #0xe5e5,-(A7) ; virgin data -- e5's work okay
- ; and with a virgin. My, you really are weird Dave.
- move.l #0x87654321,-(A7) ; magic # to make format work / fmt only
- move.w #1,-(A7) ; sector interleave factor / fmt only
- move.w #1,-(A7) ; ** side.w (relevant) / side: BACK
- move.w thetrack(A4),-(A7) ; ** track.w (relevant) / same
- move.w #10,-(A7) ; sector.w (irrelevant) / sectors per track
- move.w thedisk(A4),-(A7) ; ** device.w (relevant) / same
- move.l #0,-(A7) ; dummy.l (irreleveant) / same
- move.l buffer(A4),-(A7) ; ** buffer address.l (relevant) / same
- jsr _flopfmt
- adda.l #24,A7 ; Fix stack.
- ;*****
- ;
- ; Jazz twistsectorno(A4). Look at what it ended up as; set it to
- ; the next track twist depending on that.
- ;
- ; It will end up as "+1" from the last sector formatted, because
- ; the formatter bumps it up.
- ;
- cmpi.w #1,twistsectorno(A4) ; 0-1 transition
- beq goto1
- cmpi.w #9,twistsectorno(A4) ; 1-2 transition
- beq goto2
- cmpi.w #7,twistsectorno(A4) ; 2-3 transition
- beq goto3
- cmpi.w #5,twistsectorno(A4) ; 3-4 transition
- beq goto4
- cmpi.w #3,twistsectorno(A4) ; 4-0 transition
- beq goto0
-
- dc.b 0x4a
- dc.b 0xfc ; oops, die
-
- ;
- goto1: move.w #0x9,twistsectorno(A4) ; 9,a,1,2,3,4,5,6,7,8
- bra keepformatting
- goto2: move.w #0x7,twistsectorno(A4) ; 7,8,9,a,1,2,3,4,5,6
- bra keepformatting
- goto3: move.w #0x5,twistsectorno(A4) ; 5,6,7,8,9,a,1,2,3,4
- bra keepformatting
- goto4: move.w #0x3,twistsectorno(A4) ; 3,4,5,6,7,8,9,a,1,2
- bra keepformatting
- goto0: move.w #0x1,twistsectorno(A4) ; 1,2,3,4,5,6,7,8,9,a
- bra keepformatting
- nop
- ;
- keepformatting: nop ; entry after twisting.
- ;
-
- ;**** Setup stack: .. based on read sec command, tweaked for frammat
-
- tst.w sectoroffset(A4) ; no verify for strange sector numbers
- bne nobackside
-
- move.w #0xa,-(A7) ; count.w 2
- move.w #1,-(A7) ; ** side.w (relevant) / side: BACK 4
- move.w thetrack(A4),-(A7) ; ** track.w (relevant) / same 6
- move.w #0x1,-(A7) ; sector.w (relevant) / starting sector # 8
- move.w thedisk(A4),-(A7) ; ** device.w (relevant) / same 0xa
- move.l #0,-(A7) ; dummy.l (irreleveant) / same 0xe
- move.l buffer(A4),-(A7) ; ** buffer address.l (relevant) / same 0x12
-
- move.w #19,-(A7) ; do BIOS _flopver 0x14 (why not)
- trap #14
- adda.l #20, A7 ; fix stack
-
- tst.l D0
- bne badsecs ; wham
-
- ;****
- nobackside: nop ; entry if not DS (well at least this isn't kinky Dave)
-
- ; add 1 to thetrack. If 80, quit.
- addi.w #1, thetrack(A4)
- cmpi.w #80, thetrack(A4)
- bne trackloop ; "do another"
-
- bra gemexit ; Continue, etc, and so forth
-
- ;*********
- badsecs: move.w #0xffff, badflag(A4) ; bad sectors found
-
- ;**************
- ;
- ; End. Exit to calling routine.
- ;
- gemexit: movea.l saveA2(A4), A2 ; only reg not saved by Supexec
- rts
-
- ;******************************************************
- ;
- ;------------------------------------------------------------------------
- ; 130-ST / 520-ST :
- ; Floppy Disk Driver :
- ; (C)1985 Atari Corp. :
- ; From the FDC article (Start issue 3); shortened to just :
- ; the formatter routine and the low level I/O. :
- ; :
- ;------------------------------------------------------------------------
- ;
- ;************************************************************
- ;
- ; _flopfmt - format a track
- ; Passed (on the stack):
- ; 0x1a(A7) initial sector data
- ; 0x16(A7) magic number
- ; 0x14(A7) interleave
- ; 0x12(A7) side
- ; 0x10(A7) track
- ; 0xe(A7) A7t(A4)
- ; 0xc(A7) drive
- ; 0x8(A7) pointer to state block
- ; 0x4(A7) dma address
- ; 0x0(A7) [return]
- ;
- ; Returns: EQ: track successfully written. Zero.W-terminated list of
- ; bad sectors left in buffer (they might /all/ be bad.)
- ;
- ; NE: could not write track (write-protected, drive failure,
- ; or something catastrophic happened).
- ;-
- _flopfmt:
- cmpi.l #0x87654321, 0x16(A7) ; check for magic# on stack
- bne flopfail ; no magic, so we just saved the world
- ; bsr change ; check for disk flip
- ; moveq #e_error,D0 ; set default error number
- bsr floplock ; lock floppies, setup parms
- bsr select ; select drive and side
- move.w 0xe(A7),A7t(A4) ; save sectors-per-track
- move.w 0x14(A7),interlv(A4) ; save interleave factor
- move.w 0x1a(A7),virgin(A4) ; save initial sector data
-
- ;--- put drive into "changed" mode
- ; moveq #m_changed,D0 ; D0 = "CHANGED"
- ; bsr setdmode ; set media change mode
-
- ;--- seek to track (hard seek):
- ;debug* move.l #0xff00ff00,0xf8030
- bsr hseek ; hard seek to 'ctrack'
- ;debug* move.l #0x00000000,0xf8030
- bne flopfail ; (return error on seek failure)
- move.w ctrack(A4),dcurtrack(A1) ; record current track#
-
- ;--- format track, then verify it:
- ;* move.w #e_error,curr_err(A4)(A5) ; vanilla error mode
- ;debug* move.l #0xff00ff00,0xfA030
- bsr fmtrack ; format track
- ;debug* move.l #0x0,0xfA030
-
- bne flopfail ; (return error on seek failure)
- bra flopok
-
-
- ;****************************
- ;+
- ; fmtrack - format a track. Tweaked for skewed interleave.
- ;
- ; Passed: variables setup by _flopfmt
- ; Returns: NE on failure, EQ on success
- ; Uses: almost everything
- ; Called-by: _flopfmt
- ;
- ;-
- fmtrack:
- ;* move.w #e_write,def_error(A4) ; set default error number
- move.w #1,D3 ; start with sector 1, first pass
- ;**
- movea.l cdma(A4),A2 ; A2 = prototyping area
- ; Lay down beginning of track
-
- move.w #60-1,D1 ; 60 x 0x4e (track leadin)
- move.b #0x4e,D0
- bsr wmult
- ; Repeat 10 times: sector data.
- move.w #1,sectorno(A4) ; how many secs written
- ; Note that twistsectorno is initialized out of this routine.
- ;--- address mark
- secloop: nop
- ;
- ot1: move.w #12-1,D1 ; 12 x 0x00
- clr.b D0
- bsr wmult
- move.w #3-1,D1 ; 3 x 0xf5
- move.b #0xf5,D0
- bsr wmult
- move.b #0xfe,(A2)+ ; 0xfe -- address mark intro
- move.b ctrack+1(A4),(A2)+ ; track# - low half of word
- move.b cside+1(A4),(A2)+ ; side# - low half of word
-
- ;* #1: just use a plain sector number
- ;* move.b D4,(A2)+ ; sector#
-
- ;* #2: use a twisted sector number
- ;* move.b twistsectorno+1(A4),(A2)+ ; new: sector #.
-
- move.w twistsectorno(A4),D0 ; fetch 1-10 sector #
- ;
- ; Note that meg-a-minute backup uses sectors # 11-20 to force GEM
- ; not to use MM disks.
- ;
- add.w sectoroffset(A4),D0 ; add possible shift to 11-20 sector #
- move.b D0,(A2)+ ; plug it into sector table
-
- ; Add 1 to sector #. If it is b, wrap it to 1.
- addi.w #1,twistsectorno(A4) ; real sector # being plopped
- cmpi.w #0xb,twistsectorno(A4)
- bne notb
- move.w #1,twistsectorno(A4)
- ;
- notb: nop
- move.b #0x02,(A2)+ ; sector size (512)
- move.b #0xf7,(A2)+ ; write checksum
-
- ;--- gap between AM and data:
- move.w #22-1,D1 ; 22 x 0x4e
- move.b #0x4e,D0
- bsr wmult
- move.w #12-1,D1 ; 12 x 0x00
- clr.b D0
- bsr wmult
- move.w #3-1,D1 ; 3 x 0xf5
- move.b #0xf5,D0
- bsr wmult
-
- ;--- data block:
- move.b #0xfb,(A2)+ ; 0xfb -- data intro
- move.w #256-1,D1 ; 256 x virgin.w (initial sector data)
- ot2: move.b virgin(A4),(A2)+ ; copy high byte
- move.b virgin+1(A4),(A2)+ ; copy low byte
- dbf D1,ot2 ; fill 512 bytes
- move.b #0xf7,(A2)+ ; 0xf7 -- write checksum
- move.w #40-1,D1 ; 40 x 0x4e
- move.b #0x4e,D0
- bsr wmult
- ;
- ; Next sector, or, end-of-track. If we hit sector 11, time to quit.
- ;
- addi.w #1,sectorno(A4)
- cmpi.w #11,sectorno(A4)
- bne secloop ; loop again
- ;
- ; Okay, 10 sectors laid down.
- ;
- ;--- end-of-track
- move.w #1400,D1 ; 1401 x 0x4e -- end of track trailer
- move.b #0x4e,D0
- bsr wmult
-
- ;--- setup to write the track:
- move.b cdma+3(A4),dmalow ; load dma pointer
- move.b cdma+2(A4),dmamid
- move.b cdma+1(A4),dmahigh
- move.w #0x190,(A6) ; toggle R/W flag and
- move.w #0x090,(A6) ; select sector-count register
- move.w #0x190,(A6)
- move.w #0x1f,D7 ; (absurd sector count)
- bsr wdiskctl
- move.w #0x180,(A6) ; select 1770 cmd register
- move.w #0xf0,D7 ; write format_track command
- ;debug* move.l #0xff00ff00,0xfc030
- bsr wdiskctl
- move.l #timeout,D7 ; D7 = timeout value
-
- ;--- wait for 1770 to complete:
- otw1: btst.b #5,gpip ; is 1770 done?
- beq otw2 ; (yes)
- subq.l #1,D7 ; if(--D7) continue;
- bne otw1
- ;debug* move.l #0xffffffff,0xfc030
-
- bsr reset1770 ; timed out -- reset 1770
- oterr: moveq #1,D7 ; return NE (error status)
- rts
-
- ;--- see if the write-track won:
- otw2: nop
- ;debug* move.l #0x0,0xfc030
-
- move.w #0x190,(A6) ; check DMA status bit
- move.w (A6),D0
- btst #0,D0 ; if its zero, there was a DMA error
- beq oterr ; (so return NE)
- move.w #0x180,(A6) ; get 1770 status
- bsr rdiskctl
- ;** bsr err_bits ; set 1770 error bits
- and.b #0x44,D0 ; check for writeProtect & lostData
- rts ; return NE on 1770 error
-
- ;------ write 'D1+1' copies of D0.B into A2, A2+1, ...
- wmult: move.b D0,(A2)+ ; record byte in proto buffer
- dbf D1,wmult ; (do it again)
- rts
- ;
- ;************************************************************
- ;
- ; floplock - lock floppies and setup floppy parameters
- ;
- ; Passed (on the stack):
- ; 0x18(A7) - count.W (sector count)
- ; 0x16(A7) - side.W (side#)
- ; 0x14(A7) - track.W (track#)
- ; 0x12(A7) - sect.W (sector#)
- ; 0x10(A7) - dev.W (device#)
- ; 0xc(A7) - obsolete.L
- ; 8(A7) - dma.L (dma pointer)
- ; 4(A7) - ret1.L (caller's return address)
- ; 0(A7) - ret.L (floplock's return address)
- ;
- ; It is not coincidence that this matches the read and write input list;
- ; they call us to get stuff off stack and plug into parameters. Then,
- ; routine "select" actually pops this stuff into hardware.
- ;
- ; Passed: D0.W = default error number
- ;
- ; Also, we helpfully point A6 at the DMA chip, and A1 at the DSB.
- ;-
- floplock:
- lea regsave, A0
- movem.l D3-D7/A3-A6, (A0) ; save C registers
- lea fifo,A6 ; A6 -> fifo
- ; Start setting up param block..
- move.w D0,def_error(A4) ; set default error number
- move.w D0,curr_err(A4) ; set current error number
- ; Kick VBL off floppies..
- move.w #1,flock ; tell vbl not to touch floppies
- ; Stuff off stack:
- move.l 8(A7),cdma(A4) ; cdma -> /even/ DMA address
- move.w 0x10(A7),cdev(A4) ; save device# (0 .. 1)
- move.w 0x12(A7),csect(A4) ; save sector# (1 .. 9, usually)
- move.w 0x14(A7),ctrack(A4) ; save track# (0 .. 39 .. 79 ..)
- move.w 0x16(A7),cside(A4) ; save side# (0 .. 1)
- move.w 0x18(A7),ccount(A4) ; save sector count (1..A)
- ;--- pick a DSB: Point A1 at it.
- ; we need to check which ROMs also, if old use that
- ; otherwise assume it is a new machine
- lea dsb0new,A1 ; pick dsb 0 (drive A)
- cmpi.l #old_rom, rom_date
- bne rom1
- lea dsb0old,A1
- rom1: tst.w cdev(A4)
- beq flock2
- lea dsb1new,A1 ; pick dsb 1 (drive B)
- cmpi.l #old_rom, rom_date
- bne flock2
- lea dsb1old,A1
- ;--- compute ending DMA address from count parameter: Plug into edma.
- ; This is used in multisector transfers in read-multiple-sector,
- ; but we don't use it here.
- flock2: moveq #0,D7
- move.w ccount(A4),D7 ; edma = cdma + (ccount * 512)
- lsl.w #8,D7
- lsl.w #1,D7 ; do a 9 shift..
- movea.l cdma(A4),A0
- adda.l D7,A0
- move.l A0,edma(A4) ; save in edma
- ;--- recalibrate drive, if it needs it. This only happens when the DSB
- ; says that this drive has never awoken before, and needs an initial
- ; recal to match its current track # with the DSB track #.
- tst.w dcurtrack(A1) ; if (curtrack < 0) recalibrate()
- bpl flockr
- ; RECAL needed. Show flag about it..
- move.l #0xf0f0f0f0,0xfe000
- move.l #0xf0f0f0f0,0xfe004
-
- bsr select ; select drive & side
- clr.w dcurtrack(A1) ; we're optimistic -- assume winnage
- ; Restore.
- bsr restore ; attempt restore
- beq flockr ; (it won)
- moveq #10,D7 ; attempt seek to track 10
- bsr hseek1
- bne flock1 ; (failed)
- bsr restore ; attempt restore again
- beq flockr ; (it won)
- ;
- flock1: move.w #recal, dcurtrack(A1) ; complete failure (what can we do?)
-
- movem.l regsave(PC), D3-D7/A3-A6
- flockr: rts
- ;
- ;********************************************************************
- ;+
- ; flopfail - unlock floppies and return error.
- ; Common way for read and write to return.
- ;
- ; Note: Returns via unlok1.
- ;-
- flopfail:
- move.l #0xffffffff,D0 ; aargh, error
- bra.s unlok1 ; clobber floppy lock & return
- ;***************************************************
- ;+
- ; flopok - unlock floppies and return success status. Also a common
- ; way for r/w to return.
- ;
- ;-
- flopok: clr.l D0 ; return 0 (success)
- ; Entry point from flopfail..
- unlok1: move.l D0,-(A7) ; (save return value)
- ; I believe this code returns the FDC's status to a type-1 status, where
- ; the write protect switch is available for VBL to look at.
- move.w #datareg,(A6) ; force WP to real-time mode
- ; Sets FDC's current track register to track we are on right now.
- move.w dcurtrack(A1),D7 ; dest-track = current track
- bsr wdiskctl
- ; Does it with a "noop seek" (source=dest). Only forces FDC to type 1 status.
- move.w #0x10,D6 ; cmd = seek w/o verify
- bsr flopcmds ; do it
- ;
- unlok2: move.l (A7)+,D0 ; restore return value
- movem.l regsave(PC), D3-D7/A3-A6
- ; clear floppy lock of vblank..
- clr.w flock ; allow vblank .. unlock floppies
- ; wave byebye at the pretty camera, jenny...
- rts
- ;************************ Seek routines ********************
- ;+
- ; hseek - seek to 'ctrack(A4)' without verify
- ; hseek1 - seek to 'D7' without verify
- ; hseek2 - seek to 'D7' without verify, keep current error number
- ;
- ; Returns: NE on seek failure ("cannot happen"?)
- ; EQ if seek wins
- ;
- ; Uses: D7, D6, ...
- ; Exits to: flopcmds
- ; Called-by: _flopfmt, _flopini
- ;
- ;-
- hseek: move.w ctrack(A4),D7 ; dest track = 'ctrack'
- hseek1: nop
- hseek2: move.w #datareg,(A6) ; write destination track# to data reg
- bsr wdiskctl ; write D7 to FDC data register
- ; seek command:
- move.w #0x10,D6 ; execute "seek" command
- ; * Note: no spinup time.
- bra flopcmds ; (without verify...)
- ;
- ;***********************************************
- ;+
- ; reseek - home head, then reseek track
- ; Returns: EQ/NE on success/failure
- ; Falls-into: go2track
- ;
- ;-
- reseek:
- bsr restore ; restore head
- bne go2trr ; (punt if home fails)
-
- clr.w dcurtrack(A1) ; current track = 0
- move.w #trkreg,(A6) ; set "current track" reg on 1770
- clr.w D7
- bsr wdiskctl ; write a 00 to trk register.
-
- move.w #datareg,(A6) ; seek out to track five
- move.w #5,D7
- bsr wdiskctl ; dest track = 5
- move.w #0x10,D6
- bsr flopcmds ; seek
- ; * Note: no spinup time.
- bne go2trr ; return error on seek failure
- move.w #5,dcurtrack(A1) ; set current track#
-
- ;***********************************************+
- ; go2track - seek proper track
- ; Passed: Current floppy parameters (ctrack, et al.).
- ; Returns: EQ/NE on success/failure
- ; Calls: flopcmds
- ; Called by: read sector, for instance. Lots of places.
- ;-
- go2track:
- move.w #datareg,(A6) ; set destination track# in
- move.w ctrack(A4),D7 ; 1770's data register
- bsr wdiskctl ; (write track#)
- moveq #0x14,D6 ; execute 1770 "seek_with_verify"
- bsr flopcmds ; (include seek-rate bits)
- bne go2trr ; return error on seek failure
- move.w ctrack(A4),dcurtrack(A1) ; update current track number
- and.b #0x18,D7 ; check for RNF, CRC_error, lost_data
- go2trr: rts ; return EQ/NE on succes/failure
-
- ;*************************************************
- ;+
- ; restore - home head
- ; Passed: nothing
- ; Returns: EQ/NE on success/failure
- ;-
- restore:
- clr.w D6 ; 0x00 = 1770 "restore" command
- bsr flopcmds ; do restore
- bne res_r ; punt on timeout
- btst #2,D7 ; test TRK00 bit
- eori.w #0x04, CCR ; flip Z bit (return NE if bit is zero)
- bne res_r ; punt if didn't win
- clr.w dcurtrack(A1) ; set current track#
- res_r: rts
-
- ;****************************************************
- ; Special floppy cmd just for seeking:
- ;+
- ; flopcmds - floppy command (or-in seek speed bits from database)
- ; Passed: D6.w = 1770 command
- ; Sets-up: seek bits (bits 0 and 1) in D6.w
- ; Falls-into: flopcmd
- ; Returns: EQ/NE on success/failure
- ;
- ; I get the impression this is only used for seeking. I am right.
- ;-
- flopcmds:
- move.w dseekrt(A1),D0 ; get floppy's seek rate bits
- andi.b #3,D0 ; OR into command
- or.b D0,D6
- ; Fall in...
- ;******************************************************+
- ; flopcmd - execute any ol' 1770 command (with timeout)
- ; Passed: D6.w = 1770 command
- ;
- ; Returns: EQ/NE on success/failure
- ; D7 = 1770 status bits
- ;
- ; Note: does motor spinup, if cmd in D6 specs it (I would *hope*!)
- ;-
- flopcmd:
- move.l #timeout,D7 ; setup timeout count (assume short)
- move.w #cmdreg,(A6) ; select 1770 command register
- bsr rdiskctl ; read it to clobber READY status
- btst #7,D0 ; is motor on?
- bne flopcm ; (yes, keep short timeout)
- move.l #ltimeout,D7 ; extra timeout for motor startup
- flopcm: bsr wdiskct6 ; write command (in D6)
-
- flopc1: subq.l #1,D7 ; timeout?
- beq flopcto ; (yes, reset and return failure)
- btst.b #5,gpip ; 1770 completion?
- bne flopc1 ; (not yet, so wait some more)
- bsr rdiskct7 ; return EQ + 1770 status in D7
- clr.w D6
- rts
- ;****
- flopcto:
- ; We timed out.. a gruesome death indeed.
- ; Whap controller back to life. (Hit him harder Dave, he likes it that way)
- bsr reset1770 ; bash controller
- moveq #1,D6 ; and return NE
- rts
-
- ;*******************************************************
- ;+
- ; reset1770 - reset disk controller after a catastrophe
- ; Passed: nothing
- ; Returns: nothing
- ; Uses: D7
- ;-
- reset1770:
- move.w #cmdreg,(A6) ; execute 1770 "reset" command
- move.w #0xD0,D7 ; force interrupt
- bsr wdiskctl
- move.w #15,D7 ; wait for 1770 to stop convulsing
- r1770: dbf D7,r1770 ; (short delay loop)
- bsr rdiskct7 ; return 1770 status in D7
- rts
-
- ;******************************************************
- ;+
- ; select - setup drive select, 1770 and DMA registers
- ; Passed: cside(A4), cdev(A4)
- ; Returns: appropriate drive and side selected
- ;
- ; Called: All over the place.
- ;
- ;-
- select: move.w #0,0x9c0 ; floppies NOT deselected
- ; * lets VBL shut them off...
- move.w cdev(A4),D0 ; get device number
- addq.b #1,D0 ; add and shift to get select bits
- lsl.b #1,D0 ; into bits 1 and 2
- or.w cside(A4),D0 ; or-in side number (bit 0)
- eori.b #7,D0 ; negate bits for funky hardware select
- andi.b #7,D0 ; strip anything else out there
- bsr setporta ; do drive select
- ; Have to restore 1770's track register from table..in dsb.
- move.w #trkreg,(A6) ; setup 1770 track register
- move.w dcurtrack(A1),D7 ; from current track number
- bsr wdiskctl
- clr.b tmpdma(A4) ; zero bits 24..32 of target DMA addr
-
- ; Setup R/W parameters on 1770. Used by
- ; r/w sector, among others. This is where the sector register gets set.
- ;
- select1:
- move.w #secreg,(A6) ; setup requested sector_number from
- move.w csect(A4),D7 ; caller's parameters
- bsr wdiskctl
- move.b cdma+3(A4),dmalow ; setup DMA chip's DMA pointer
- move.b cdma+2(A4),dmamid
- move.b cdma+1(A4),dmahigh
- rts
-
- ;************************************************
- ;+
- ; setporta - set floppy select bits in PORT A on the sound chip
- ; Passed: D0.b (low three bits)
- ; Returns: D1 = value written to port A
- ; D2 = old value read from port A
- ; Uses: D1
- ;-
- setporta:
- move SR,-(A7) ; save our IPL
- ori #0x0700,SR ; start critical section
- move.b #giporta,giselect ; select port on GI chip
- move.b giread,D1 ; get current bits
- move.b D1,D2 ; save old bits for caller
- andi.b #0xff-7,D1 ; strip low three bits there
- or.b D0,D1 ; or-in our new bits
- move.b D1,giwrite ; and write 'em back out there
- move (A7)+,SR ; restore IPL to terminate CS, return
- rts
-
- ;**************************************************
- ;+
- ; Primitives to read/write 1770 controller chip (DISKCTL register).
- ;
- ; The 1770 can't keep up with full-tilt CPU accesses, so
- ; we have to surround reads and writes with delay loops.
- ; This is not really as slow as it sounds.
- ;
- wdiskct6: ; write D6 to diskctl
- bsr rwdelay ; delay
- move.w D6,diskctl ; write it
- bra rwdelay ; delay and return
-
- wdiskctl: ; write D7 to diskctl
- bsr rwdelay ; delay
- move.w D7,diskctl ; write it
- bra rwdelay ; delay and return
-
- rdiskct7: ; read diskctl into D7
- bsr rwdelay ; delay
- move.w diskctl,D7 ; read it
- bra rwdelay ; delay and return
-
- rdiskctl: ; read diskctl into D0
- bsr rwdelay ; delay
- move.w diskctl,D0 ; read it
- ; And here's the delay loop:
- rwdelay:
- move SR,-(A7) ; save flags
- move.w D7,-(A7) ; save counter register
- move.w #0x20,D7 ; 0x20 seems about right...
- rwdly1: dbf D7,rwdly1 ; busy-loop: give 1770 time to settle
- move.w (A7)+,D7 ; restore register, flags, and return
- move (A7)+,SR
- rts
-
- ;-------------------------------------
- regsave: dc.l 1 ; PC relative data area
- dc.l 2
- dc.l 3
- dc.l 4
- dc.l 5
- dc.l 6
- dc.l 7
- dc.l 8
- dc.l 9
-
-
- } /* MY GOD! It's DONE! */
-